home *** CD-ROM | disk | FTP | other *** search
- /* Functions for creating and displaying an alert which is not read in
- from a resource, and is therefore called a "fake" alert. This is most
- useful for reporting Resource Manager errors. The total dynamic heap
- memory needed to display the alert is fairly small since most of the
- data structures are allocated on the stack or in static memory.
-
- Since the alert is to be displayed in response to a Resource Manager
- error, it wouldn't make sense to try to read the error strings in
- from the resource file. Therefore, there are a few hard-coded strings
- in this file, such as the titles of the ok and cancel buttons, and the
- basic string for a Resource Manager error.
-
- This file makes calls only to the Macintosh Toolbox. It does not call
- any private libraries or any of the standard C libraries. It only
- requires that TEInit has been called and it requires a minimal amount
- of memory to create and display a window containing an alert message.
-
- Revision History:
-
- 93/12/15 aih
- - fixed error in calculation of bottom of text rectangle
-
- 93/11/22 aih
- - Only Pascal strings are used, so I don't need any C to Pascal conversion
- functions
- - Removed all uses of the ANSI library, so that this library is not
- depended on code other than the what was available in the 64K ROMs.
-
- 93/11/13 aih
- - ShowHide is used instead of ShowWindow/HideWindow so activate/deactivate
- events aren't generated
-
- 93/10/25 aih
- - made alert bigger
- - made first button's position relative to window's lower right corner,
- instead of hard-coding the coordinates
-
- 93/10/19 AIH
- - Expanded a few comments
-
- 93/03/23 AIH
- - Removed use of MathLib.c and MacLib.c, since those
- files could be in a different segment
-
- 93/03/19 AIH
- - Added AlertFakeOSErr
- - Changed AlertFakeLibBegin to AlertFakeInit
-
- 93/03/13 AIH
- - Moved private defines from header into this file
-
- 91/05/06 AIH
- - Fixed bug with icon plotting if ResLoad was false
-
- 91/04/24 AIH
- - Added function to reset the alert after it has been run; this is
- needed for the preloaded alert
-
- 91/04/22 AIH
- - Removed dependence on things available only in "newer" system software;
- it's my guess that the functions in this file will work correctly even
- with very old system software
-
- 91/04/17 AIH
- - The alert's port isn't set after NewWindow is called
-
- 91/04/10 AIH
- - Alerts can be preloaded
-
- 91/03/24 AIH
- - Adapted to use key library function for international canceling
-
- 91/03/23 AIH
- - Updated a few of the comments.
-
- 91/03/02 AIH
- - Update events are only handled if they apply to the alert's window
-
- 91/02/28 AIH
- - Call event library instead of WNE
-
- 91/02/08 AIH
- - Storage for alert is allocated on stack instead of statically
-
- 91/01/21 Ari Halberstadt (AIH)
- - Created this library to report resource manager errors, especially
- resource manager errors in the Dialog Manager. */
-
- #include <stdarg.h>
- #include "AlertFakeLib.h"
-
- /* maximum number of buttons */
- #define ALERT_MAXBUTTON (3)
-
- /* parameters for setting the position and size of the alert */
- #define MARGIN (8)
- #define ALERT_TOP (0)
- #define ALERT_LEFT (0)
- #define ALERT_WIDTH (72 * 5)
- #define ALERT_HEIGHT (72 * 2)
- #define BUTTON_WIDTH (72)
- #define BUTTON_HEIGHT (20)
- #define BUTTON_TOP (ALERT_HEIGHT - BUTTON_HEIGHT - MARGIN)
- #define BUTTON_LEFT (ALERT_WIDTH - BUTTON_WIDTH - MARGIN)
- #define ICON_TOP (10)
- #define ICON_LEFT (20)
- #define ICON_WIDTH (32)
- #define ICON_HEIGHT (32)
- #define TEXT_TOP (ALERT_TOP + MARGIN)
- #define TEXT_LEFT (ICON_LEFT + ICON_WIDTH + 20)
- #define TEXT_BOTTOM (BUTTON_TOP - MARGIN)
- #define TEXT_RIGHT (ALERT_WIDTH - MARGIN)
-
- typedef struct {
- WindowRecord windowRec; /* storage for the window */
- WindowPtr window; /* pointer to the window */
- Rect windowRect; /* window's rectangle */
- Rect textRect; /* text's rectangle */
- Rect iconRect; /* icon's rectangle */
- short iconid; /* resource id of icon */
- short okbut; /* ok button */
- short cancelbut; /* cancel button */
- short clicked; /* button clicked */
- short nbuttons; /* number of buttons */
- StringPtr text; /* text displayed */
- ControlHandle button[ALERT_MAXBUTTON]; /* list of buttons */
- } AlertFakeType;
-
- /* strings that aren't read from resources */
- #define TEXT_OK ((StringPtr) "\pOK")
- #define TEXT_CANCEL ((StringPtr) "\pCancel")
- #define TEXT_OSERR ((StringPtr) "\pError #%d occurred.")
- #define TEXT_RES ((StringPtr) "\pCould not get a resource (error #%d).")
- #define TEXT_MEM ((StringPtr) "\pOut of memory.")
- #define TEXT_FAILED ((StringPtr) "\pCould not complete the operation.")
-
- /* the alert that's created when the library is initialized */
- static AlertFakeType gAlertOk;
-
- /* a handle used for formatting text strings for display */
- static Handle gTextHandle;
-
- /* fill with nulls */
- static void memzap(void *p, long n)
- {
- char *q = p;
- while (n-- > 0) *q++ = 0;
- }
-
- /* position the rectangle within the main screen */
- static void PositionInScreen(Rect *r)
- {
- Rect scrn;
- Point pos;
- SysEnvRec world;
-
- scrn = screenBits.bounds;
- (void) SysEnvirons(curSysEnvVers, &world);
- scrn.top += ((world.systemVersion >= 0x0410) ? GetMBarHeight() : 20);
- pos.h = scrn.left + ((scrn.right - scrn.left) - (r->right - r->left)) / 2;
- pos.v = scrn.top + ((scrn.bottom - scrn.top) - (r->bottom - r->top)) / 3;
- OffsetRect(r, pos.h - r->left, pos.v - r->top);
- }
-
- /* draw the alert's buttons */
- static void AlertFakeDrawButtons(AlertFakeType *alrt)
- {
- DrawControls(alrt->window);
- }
-
- /* draw the text of the alert */
- static void AlertFakeDrawText(AlertFakeType *alrt)
- {
- GrafPtr port;
-
- GetPort(&port);
- SetPort(alrt->window);
- if (alrt->text)
- TextBox(alrt->text + 1, *alrt->text, &alrt->textRect, teJustLeft);
- else
- EraseRect(&alrt->textRect);
- SetPort(port);
- }
-
- /* draw the alert's icon */
- static void AlertFakeDrawIcon(AlertFakeType *alrt)
- {
- GrafPtr port;
- Handle icon;
-
- GetPort(&port);
- SetPort(alrt->window);
- icon = GetIcon(alrt->iconid);
- if (icon && *icon)
- PlotIcon(&alrt->iconRect, icon);
- SetPort(port);
- }
-
- /* draw the alert */
- static void AlertFakeDraw(AlertFakeType *alrt)
- {
- AlertFakeDrawButtons(alrt);
- AlertFakeDrawText(alrt);
- AlertFakeDrawIcon(alrt);
- }
-
- /* return item clicked in alert */
- static short AlertFakeClicked(AlertFakeType *alrt)
- {
- return(alrt->clicked);
- }
-
- /* make the alert visible */
- static void AlertFakeShow(AlertFakeType *alrt)
- {
- InitCursor();
- FlushEvents(everyEvent, 0);
- BringToFront(alrt->window);
- HiliteWindow(alrt->window, true);
- ShowHide(alrt->window, true);
- SysBeep(5);
- }
-
- /* make the alert invisible */
- static void AlertFakeHide(AlertFakeType *alrt)
- {
- ShowHide(alrt->window, false);
- FlushEvents(everyEvent, 0);
- }
-
- /* add button to alert */
- static void AlertFakeButton(AlertFakeType *alrt, const StringPtr title)
- {
- Rect bounds;
- short width = 0;
- ControlHandle button = NULL;
-
- if (alrt->nbuttons < ALERT_MAXBUTTON) {
- if (alrt->nbuttons > 0) {
- bounds = (**alrt->button[alrt->nbuttons-1]).contrlRect;
- bounds.right = bounds.left - 16;
- }
- else {
- SetRect(&bounds, BUTTON_LEFT, BUTTON_TOP,
- BUTTON_LEFT + BUTTON_WIDTH, BUTTON_TOP + BUTTON_HEIGHT);
- }
- button = NewControl(alrt->window, &bounds, title, true, 0, 0, 1,
- pushButProc, 0);
- if (button)
- alrt->button[alrt->nbuttons++] = button;
- }
- }
-
- /* set alert's icon */
- static void AlertFakeIcon(AlertFakeType *alrt, short iconid)
- {
- alrt->iconid = iconid;
- AlertFakeDrawIcon(alrt);
- }
-
- /* set alert's text */
- static void AlertFakeText(AlertFakeType *alrt, const StringPtr text)
- {
- alrt->text = (StringPtr) text;
- AlertFakeDrawText(alrt);
- }
-
- /* handle a click in the alert at the given point */
- static void AlertFakeClick(AlertFakeType *alrt, Point pt)
- {
- ControlHandle button; /* button clicked */
- short part; /* part of control where event occurred */
- short i; /* index to buttons */
-
- part = FindControl(pt, alrt->window, &button);
- if (part == inButton && TrackControl(button, pt, 0L) == inButton) {
- for (i = 0; i < alrt->nbuttons && alrt->button[i] != button; i++)
- ;
- if (i < alrt->nbuttons)
- alrt->clicked = i + 1;
- }
- }
-
- /* handle a single event in the alert */
- static void AlertFakeEvent(AlertFakeType *alrt, EventRecord *event)
- {
- short where; /* where mouse was clicked */
- WindowPtr window; /* window in which mouse was clicked */
- ControlHandle control; /* control in which mouse was clicked */
- Point pt; /* where event occurred in local coordinates */
- GrafPtr port; /* saved port */
- unsigned char key; /* key hit by user */
-
- /* set port to alert's window */
- GetPort(&port);
- SetPort(alrt->window);
-
- /* handle the event */
- switch (event->what) {
- case mouseDown:
- /* handle a click in the button */
- where = FindWindow(event->where, &window);
- if (where == inContent && window == alrt->window) {
- pt = event->where;
- GlobalToLocal(&pt);
- AlertFakeClick(alrt, pt);
- }
- else
- SysBeep(5);
- break;
-
- case updateEvt:
- if ((WindowPtr)event->message == alrt->window) {
- BeginUpdate(alrt->window);
- AlertFakeDraw(alrt);
- EndUpdate(alrt->window);
- }
- break;
- }
-
- /* restore port */
- SetPort(port);
- }
-
- /* handle events in the alert */
- static void AlertFakeRun(AlertFakeType *alrt)
- {
- EventRecord event;
-
- /* wait for user to click a button */
- while (! AlertFakeClicked(alrt)) {
- if (GetNextEvent(everyEvent, &event))
- AlertFakeEvent(alrt, &event);
- }
- }
-
- /* reset the alert */
- static void AlertFakeReset(AlertFakeType *alrt)
- {
- alrt->clicked = 0;
- }
-
- /* setup the alert */
- static void AlertFakeBegin(AlertFakeType *alrt)
- {
- GrafPtr port = NULL;
-
- /* clear everything */
- memzap(alrt, sizeof(AlertFakeType));
-
- /* set up rectangles */
- SetRect(&alrt->windowRect, ALERT_LEFT, ALERT_TOP,
- ALERT_LEFT + ALERT_WIDTH, ALERT_TOP + ALERT_HEIGHT);
- SetRect(&alrt->textRect, TEXT_LEFT, TEXT_TOP,
- TEXT_RIGHT, TEXT_BOTTOM);
- SetRect(&alrt->iconRect, ICON_LEFT, ICON_TOP,
- ICON_LEFT + ICON_WIDTH, ICON_TOP + ICON_HEIGHT);
-
- /* set buttons */
- alrt->okbut = ok;
- alrt->cancelbut = cancel;
-
- /* create window */
- GetPort(&port);
- alrt->window = (WindowPtr) &alrt->windowRec;
- PositionInScreen(&alrt->windowRect);
- NewWindow((WindowPeek) alrt->window, &alrt->windowRect,
- (StringPtr) "\pAlert", false, dBoxProc, (WindowPtr) -1L, false, 0L);
- SetPort(alrt->window);
- TextFont(systemFont);
- SetPort(port);
- }
-
- /* end the alert */
- static void AlertFakeEnd(AlertFakeType *alrt)
- {
- while (alrt->nbuttons > 0)
- DisposeControl(alrt->button[--alrt->nbuttons]);
- CloseWindow(alrt->window);
- alrt->window = NULL;
- }
-
- /* Setup and run a generic alert. */
- short AlertFakeGeneric(const StringPtr text, short iconid, short count, ...)
- {
- AlertFakeType alrt;
- va_list ap;
- short result = 0;
-
- AlertFakeBegin(&alrt);
- AlertFakeText(&alrt, text);
- AlertFakeIcon(&alrt, stopIcon);
- va_start(ap, count);
- while (count-- > 0)
- AlertFakeButton(&alrt, va_arg(ap, StringPtr));
- va_end(ap);
- AlertFakeShow(&alrt);
- AlertFakeRun(&alrt);
- result = AlertFakeClicked(&alrt);
- AlertFakeEnd(&alrt);
- return(result);
- }
-
- /* display an alert with an ok button */
- void AlertFakeOk(const StringPtr text, short icon)
- {
- static Boolean using;
-
- /* see if we can use the preloaded alert */
- if (gAlertOk.window && ! using) {
- using = true;
- AlertFakeText(&gAlertOk, text);
- AlertFakeIcon(&gAlertOk, icon);
- AlertFakeShow(&gAlertOk);
- AlertFakeRun(&gAlertOk);
- AlertFakeHide(&gAlertOk);
- AlertFakeReset(&gAlertOk);
- using = false;
- }
- else /* it wasn't created or it's already in use so create a new alert */
- AlertFakeGeneric(text, icon, 1, TEXT_OK);
- }
-
- /* display an alert with ok and cancel buttons */
- Boolean AlertFakeOkCancel(const StringPtr text, short icon)
- {
- return(AlertFakeGeneric(text, icon, 2, TEXT_OK, TEXT_CANCEL) == ok);
- }
-
- /* display an alert for an error number */
- static void AlertFakeErr(OSErr err, const StringPtr format)
- {
- Handle text = gTextHandle;
- Str31 num;
-
- if (text) {
- SetHandleSize(text, *format + 1);
- if (MemError() == noErr) {
- NumToString(err, num);
- BlockMove(format, *text, *format + 1);
- Munger(text, 1, "%d", 2, num+1, *num);
- **text = GetHandleSize(text) - 1;
- MoveHHi(text);
- HLock(text);
- AlertFakeOk((StringPtr) *text, stopIcon);
- HUnlock(text);
- SetHandleSize(text, sizeof(Str255));
- }
- }
- }
-
- /* display an alert for a failed exception */
- void AlertFakeFailed(OSErr err, const StringPtr text)
- {
- if (err)
- AlertFakeOSErr(err);
- else if (text && *text)
- AlertFakeOk(text, stopIcon);
- else
- AlertFakeOk(TEXT_FAILED, stopIcon);
- }
-
- /* display an alert for an operating system error */
- void AlertFakeOSErr(OSErr err)
- {
- AlertFakeErr(err, TEXT_OSERR);
- }
-
- /* display an alert for a resource error */
- void AlertFakeRes(OSErr err)
- {
- AlertFakeErr(err, TEXT_RES);
- }
-
- /* display an alert for a low memory situation; there should be enough
- memory to show the window, or this may crash */
- void AlertFakeMem(void)
- {
- AlertFakeOk(TEXT_MEM, cautionIcon);
- }
-
- /* initialize the fake alert library by pre-creating a fake alert */
- void AlertFakeInit(void)
- {
- if (! gTextHandle) {
- AlertFakeBegin(&gAlertOk);
- AlertFakeButton(&gAlertOk, TEXT_OK);
- gTextHandle = NewHandle(sizeof(Str255));
- }
- }
-